﻿// Manipulates a layout for an element
define([
    'Wjs/Wjs'
],
function () {
    'use strict';

    var LayoutHolder = Wjs.defineOnce({

            type: 'LayoutHolder',

            internal: {

                construct: function (cfg, parent) {

                    cfg = cfg || {};

                    this.setLayout(cfg.layout || this.layout); // Only a single layout can exist for an element at a time. The configuration one overrides the type one

                    this.onUpdateLayout = cfg.onUpdateLayout || this.onUpdateLayout;
                },

                listeners: {

                    onBeforeDomElementCreated: function () {
                        this.configureLayout();
                    },


                    onElementResized: function () {
                        this.updateLayout();
                    },

                    onElementVisible: function () {
                        this.updateLayout();
                    }
                }
            },

            setLayout: function (layout) {

                if (!layout) {
                    this.layout = null;

                    return;
                }

                if (Wjs.isString(layout)) {
                    this.layout = Wjs.getType(layout);
                }
                else {
                    this.layout = Wjs.create(layout);
                }
            },

            // Configures the layout of the element before being rendered since it might require adding or changing the position of the elements
            configureLayout: function () {

                if (this.layout && this.layout.prototype.configure) {
                    this.layout.prototype.configure(this);
                }

                // No need to propagate to its children since the children initialize their layout when rendered as well
            },

            // Updates the layout of this element and notifies its children if any
            // In order to not call the children update more than once, we use the skipChildren flag which is set to true by the parent
            updateLayout: function (skipChildren) {

                if (!this.isRendered()) { // Should never happen but in case
                    throw 'Element must be rendered in order to update its layout';
                }

                if (this.hidden) {
                    return; // No need to update the layout of hidden elements
                }

                if (this.layout && this.layout.prototype.update) {
                    this.layout.prototype.update(this);
                }

                if (this.onUpdateLayout) {
                    this.onUpdateLayout();
                }

                if (skipChildren) {
                    return; // Done
                }

                this.down(function (c) {
                    return c.updateLayout; // The child has the update layout method
                })
                .forEach(function (c) {
                    c.updateLayout(true); // Have them not to call their children
                },
                this);
            }

        });

    return LayoutHolder;
});